package components
{
	import flash.display.BitmapData;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.FocusEvent;
	import flash.events.KeyboardEvent;
	import flash.events.MouseEvent;
	import flash.text.TextField;
	import flash.text.TextFieldAutoSize;
	import flash.text.TextFieldType;
	import flash.ui.Keyboard;
	
	import oboe.controllers.Collection;
	import oboe.core.Controller;
	import oboe.core.Oboe;
	import oboe.math.Number3D;
	import oboe.utils.CallbackHandle;
	import oboe.utils.Prototype;
	
	public class Circle extends Component
	{
		protected var fillColor:uint = 0xFFFF7777;
		public var text:String = "";
		protected var autoRadius:Boolean = true;
		protected var radius:Number = 0;
		protected var minRadius:Number = 10;
		
		private var circle:Sprite;
		private var label:TextField;
		private var inLinks:Collection = new Collection();
		private var outLinks:Collection = new Collection();
		
		private var mode:String;
		private static const modeColors:Object = {
			normal : 0,
			pivot : 0xFFFFFF
		};
		
		private static const tmpbmp:BitmapData = new BitmapData(1,1,false);
		
		public function Circle( data:Object=null, autoEdit:Boolean=false )
		{
			super( null, data );

			this.mode = "normal"; 
			
			this.draw();
			
			if( autoEdit )
			{
				this.startInputMode();
				this.setSelected(true);
			}
		}
		
		override protected function createData( data:Object ):ComponentData
		{
			return new CircleData( data );
		}
		
		protected override function selfDestruct():void
		{
			this.outLinks.message("destruct");
			this.inLinks.message("destruct");
			super.selfDestruct();
		}
		
		protected function draw():void
		{
			if( !this.circle )
			{
				this.circle = this.getDisplayObject() as Sprite;
				with( this.circle as Object )
				{
					mouseChildren = false;
					buttonMode = true;
					doubleClickEnabled = true;
					// addCallbackEx(MouseEvent.CLICK, onClick);
					// addCallback(MouseEvent.DOUBLE_CLICK, startInputMode);
					// addCallback(Event.ADDED_TO_STAGE, startInputMode);
					// addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
				}

				this.label = new TextField();
				this.label.autoSize = TextFieldAutoSize.LEFT;
				this.label.focusRect = false;
				this.circle.addChild( this.label );
			}
			
			if( this.label.text != this.text )
			{
				this.label.text = this.text;
				if( this.autoRadius )
				{
					tmpbmp.draw( this.label );
					this.radius = this.label.width * 0.6;
					this.label.y = -this.label.height/2;
					this.label.x = -this.label.width/2;
				}
			}
			
			this.radius = Math.max( this.radius, this.minRadius );
			
			this.circle.graphics.clear();
			this.circle.graphics.beginFill( this.fillColor );
			this.circle.graphics.lineStyle( 2, modeColors[ this.mode ] );
			this.circle.graphics.drawCircle( 0, 0, this.radius );
			this.circle.graphics.endFill();
		}
		
		[slot] public function getOrbit( orbit:Number3D ):void
		{
			orbit.x = this.circle.x;
			orbit.y = this.circle.y;
			orbit.z = this.radius;
		}			
		
		[slot] public function linkTo( other:Component, link:Link ):void
		{
			if( !other is Circle ) return; 
			this.outLinks.add( link );
			Circle(other).inLinks.add( link );
			this.signalUp( "addElement", link ); 
		}
		
		[slot] public function removeLink( link:Controller ):void
		{
			this.inLinks.remove( link );
			this.outLinks.remove( link );
		}
		
		[slot] public function getText( ret:Array ):void
		{
			ret.push( this.text );
		}
		
		private var cbs:Array;
		
		[slot] public override function setSelected(state:Boolean):void
		{
			super.setSelected(state);
			this.mode = state?"pivot":"normal";
			this.draw();
		}
		
		[slot] public function startInputMode():void
		{
			this.circle.mouseChildren = true;
			this.label.type = TextFieldType.INPUT;
			this.label.border = true;
			this.label.background = true;
			this.label.backgroundColor = 0xFFFFFF;
			Oboe.stage.focus = this.label;
			this.label.setSelection(0, this.text.length);
			cbs = [
				Prototype.addCallback( this.label, FocusEvent.FOCUS_OUT, endInputMode ),
				Prototype.addCallbackEx( this.label, KeyboardEvent.KEY_DOWN, function(e:KeyboardEvent):void
				{
					if( e.keyCode == Keyboard.ENTER ) endInputMode();
					if( e.keyCode == Keyboard.ESCAPE )
					{
						label.text = text;
						endInputMode();
					}
				} ),
			]
		}
		
		private function endInputMode( ):void
		{
			for each( var cb:CallbackHandle in cbs )
			{
				Prototype.removeCallback( this.label, cb );
			}
			this.circle.mouseChildren = false;
			this.label.type = TextFieldType.DYNAMIC;
			this.label.border = false;
			this.label.background = false;
			var nt:String = this.label.text;
			this.label.text = this.text;
			this.text = nt;
			this.draw();
			this.inLinks.message("orbitChanged", this);
			this.outLinks.message("orbitChanged", this);
		}
		
		protected override function setPosition(x:Number, y:Number):void
		{
			super.setPosition( x, y );
			this.inLinks.message("orbitChanged", this);
			this.outLinks.message("orbitChanged", this);
		}
	}
}